package org.ala.tiktools.generator.mybatis.dbinfo;

import com.mysql.cj.xdevapi.Table;

import java.io.UnsupportedEncodingException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 数据库信息获取器
 *
 * @author ala
 * @date 2025-03-13 15:58
 */
public class DBInfoGatter {


    /**
     *  取表信息
     */
    public TableInfo getTable(Connection conn, String db, String table) {
        ResultSet rs = null;
        try {
            rs = conn.getMetaData().getTables(db, "%", table, new String[]{"TABLE"});
            rs.next();

            TableInfo tinfo = new TableInfo();
            //  取真实表名，表表述
            tinfo.setName(rs.getString("TABLE_NAME"));
            tinfo.setDesc(rs.getString("REMARKS"));
            return tinfo;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     *  获取表的全部字段
     */
    public List<ColumnInfo> getColumns(Connection conn, String db, String table) throws SQLException {
        DatabaseMetaData metaData = conn.getMetaData();

        ResultSet rs = null;

        Set<String> set = new HashSet<>();
        List<ColumnInfo> columns = new ArrayList<>();
        try {
            String pk = getOnlyPrimaryKey(metaData, db, table);

            //  取字段信息
            rs = metaData.getColumns(db, "%", table, "%");
            while (rs.next()) {
                String name = rs.getString("COLUMN_NAME");
                //  COLUMN_DEF  IS_AUTOINCREMENT
                if (!set.add(name)) {continue;}

                String type = rs.getString("TYPE_NAME").split(" ")[0];;
                String desc = encoding(rs.getString("REMARKS"), "utf-8");
                String isGenerated = rs.getString("IS_GENERATEDCOLUMN");
                String isAutoIncrement = rs.getString("IS_AUTOINCREMENT");
                boolean onlyAutoIncrementPrimaryKey = false;
                //  如果是一位主键字段，并且自己是自增的
                if (name.equals(pk) && "YES".equalsIgnoreCase(isAutoIncrement)) {
                    onlyAutoIncrementPrimaryKey = true;
                }

                columns.add(ColumnInfo.build(name, type, desc, "YES".equalsIgnoreCase(isGenerated), onlyAutoIncrementPrimaryKey));
            }
            return columns;
        } catch (SQLException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     *  取唯一主键字段名
     */
    protected String getOnlyPrimaryKey(DatabaseMetaData metaData, String db, String table) throws SQLException {
        ResultSet rs = metaData.getIndexInfo(db, "%", table, true, true);
        boolean find = false;
        List<String> columns = new ArrayList<>();
        while (rs.next()) {
            String indexType = rs.getString("TYPE"),
                    indexName = rs.getString("INDEX_NAME"),
                    cn = rs.getString("COLUMN_NAME");
            if (indexName.equals("PRIMARY")) {
                columns.add(cn);
            }
        }

        return columns.size() == 1 ? columns.get(0) : null;
    }
    protected String encoding(String str, String charset) throws UnsupportedEncodingException {
        if (str == null) {return null;}
        str = str.replaceAll("\\n", "\t").replaceAll("\\\"", "\\\\\"");
        str = new String(str.getBytes(), charset);
        return str;
    }


    /**
     *  搜索所有分表语句
     */
    public String getAllTablesSql(String db, String table) throws SQLException {
        String sql = "SELECT table_name FROM information_schema.tables  AS TABLE_NAME WHERE table_schema = '" + db + "' AND table_name LIKE '" + table + "%'";
        return sql;
    }


    /**
     *  拿到建表语句
     */
    protected String getCreateSql(Connection conn, String db, String table) throws SQLException {
        String sql = String.format("show create table `%s`.`%s`", db, table);
        Statement stmp = conn.createStatement();
        ResultSet rs = stmp.executeQuery(sql);
        rs.next();
        String createSql =  rs.getString("Create Table");
        //  替换表名的占位符
        createSql = createSql.replaceAll(String.format("`%s`", table), String.format("`%s_\\$\\{shardSuffix\\}`", table));
        createSql += ";";
        return createSql;
    }
    /**
     *  拿建索引语句
     */
    protected List<String> getCreateIndexSql(Connection conn, String db, String table) throws SQLException {
        String sql = String.format("show index from `%s`.`%s`", db, table);
        Statement stmp = conn.createStatement();
        ResultSet rs = stmp.executeQuery(sql);
        List<IndexInfo> idxes = new ArrayList<>();
        IndexInfo crt = null;
        while (rs.next()) {
            String name = rs.getString("Key_name");
            //  主键不参与生成
            if (name.equals("PRIMARY")) {continue;}

            if (crt == null || !crt.getName().equals(name)) {
                crt = IndexInfo.build().name(name).columns(new ArrayList<>()).table(table);
                idxes.add(crt);
            }
            crt.unique(rs.getInt("Non_unique") == 0)
                    .appendColumn(IndexInfo.Field.build(rs.getString("Column_name"), rs.getString("Collation").equals("A")))
                    .packed(rs.getString("Packed"))
                    .indexType(rs.getString("Index_type"))
                    .comment(rs.getString("Comment"));
        }
        return idxes.stream().map(IndexInfo::toSql).collect(Collectors.toList());
    }
}
